#include "parent.hpp"

bool inside_writeToFile(const std::string& fileName, const std::string str)
{
    std::fstream s(fileName, s.out);
    if (!s.is_open()) {
        return false;
    } else {
        s << str;
        s.close();
        return true;
    }
}

bool inside_writeToFileAppend(const std::string& fileName, const std::string str)
{
    std::fstream s(fileName, s.out|s.app);
    if (!s.is_open()) {
        return false;
    } else {
        s << str;
        s.close();
        return true;
    }
}

bool inside_readFromFile(const std::string& fileName, std::string& str)
{
	std::ifstream fin(fileName, std::ios::in);
    if (!fin.is_open()) {
        return false;
    } else {
		str.clear();
		char line[65536] = {0};
		while(fin.getline(line, sizeof(line)))
		{
			std::string temps(line);
			str.append(temps.begin(), temps.end());
		}
		fin.clear();
		fin.close();
		return true;
    }
}

/*
 * parent process, used directedly by after fork
 * para: struct structConfig mconfig: config information,
 *   int pid(child process id)
 * return: code of struct_runOneCaseTest.code (GBL struct)
 *
 * note: parent write the info.txt
 */
int ParentProcess(struct structConfig mconfig, int pid){
	//wait for child exit
    int status;
    struct rusage resource_usage;
    if (wait4(pid, &status, WSTOPPED, &resource_usage) == -1) {
        kill(pid, SIGKILL);
		return GBL_JSBP_OUTER_ERROR_WAIT_CHILD;
    }
    
	//get memory and time
    long long memory = resource_usage.ru_maxrss * 1024;  //note here get unit: "b" because * 1024!
    int cpuTime = (int)(resource_usage.ru_utime.tv_sec * 1000 + resource_usage.ru_utime.tv_usec / 1000);
	
	//save time and memory
	if (!inside_writeToFile(mconfig.dir + mconfig.testID + RunTimePos, to_string(cpuTime)))
		return GBL_JSBP_OUTER_ERROR_SAVE_INFO;
	if (!inside_writeToFile(mconfig.dir + mconfig.testID + RunMemoryPos, to_string(memory)))
		return GBL_JSBP_OUTER_ERROR_SAVE_INFO;

	//convert runtest(JSBC) code to JSBP code
    if (WIFEXITED(status)){
		int exitCode = WEXITSTATUS(status);
		if (exitCode == GBL_JSBC_RUNTEST_OK){
			if (mconfig.maxMemory != UNLIMITED && memory > mconfig.maxMemory) {
				return GBL_JSBP_RES_MLE;
			}
			else
			{
				return GBL_JSBP_RES_AC;
			}
		}
		else if (exitCode == GBL_JSBC_RUNTEST_WA){
			return GBL_JSBP_RES_WA;
		}
		else if (exitCode == GBL_JSBC_RUNTEST_OVERFLOW){
			return GBL_JSBP_RES_OF;
		}
		else if (exitCode == GBL_JSBC_RUNTEST_ERROR_PARA || exitCode == GBL_JSBC_RUNTEST_INPUT_NOTFOUND || exitCode == GBL_JSBC_RUNTEST_INPUT_DATA_INVALID || exitCode == GBL_JSBC_RUNTEST_OUTPUT_CANNOT_SAVE)
			return GBL_JSBP_RES_ERROR;
		else if (exitCode == GBL_JSBC_RUNTEST_DEBUG){
			return GBL_JSBP_RES_DEBUG;
		}
		else{
			return GBL_JSBP_RES_UNKNOWN;
		}
    }
    else if (WIFSIGNALED(status)){
		//retstr = retstr + "program killed by " + to_string(WTERMSIG(status)) + "\n";
        if (WTERMSIG(status) == SIGSEGV){
            if (mconfig.maxMemory != UNLIMITED && memory > mconfig.maxMemory) {
				return GBL_JSBP_RES_MLE;
            }
            else {
				return GBL_JSBP_RES_RE;
            }
        }
        else if (WTERMSIG(status) == SIGXCPU){
			return GBL_JSBP_RES_TLE;
        }
        else{
            if (mconfig.maxMemory != UNLIMITED && memory > mconfig.maxMemory) {
				return GBL_JSBP_RES_MLE;
            }
            else{
				return GBL_JSBP_RES_RE;
            }
        }
    }
	else{
		return GBL_JSBP_OUTER_ERROR_UNKNOWN_CHILD;
	}
}
